package com.test.spring.util.aspect.datasource;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.MessageFormat;

/**
 * 动态切换数据源
 *
 * Created by ll on 2017/2/13.
 */
public class DataSourceAspect {
    private static final Logger LOG = LoggerFactory.getLogger(DataSourceAspect.class);

    /**
     * 配置前置通知,使用在方法aspect()上注册的切入点
     */
    @Before("aspect()")
    public void before(JoinPoint point) {
        StringBuilder dc = new StringBuilder();
        if (StringUtils.isNotBlank(getDataSourceForType(point))){
            dc.append(getDataSourceForType(point));
        }
        //设置
        DataSourceHandle.setDataSource(dc.toString());
    }

    @After("aspect()")
    public void after() {
        //清空
        DataSourceHandle.cleanDataSource();
    }

    /**
     * 获取方法或类的注解对象DataSource值
     * 读写分离
     * @param point      类class
     * @return DataSource
     */
    private String getDataSourceForType(JoinPoint point) {
        Class<?> target = point.getTarget().getClass();
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        try {
            //1.优先方法注解
            Class<?>[] types = method.getParameterTypes();
            Method m = target.getMethod(method.getName(), types);
            if (m != null && m.isAnnotationPresent(DataSource.class)) {
                return m.getAnnotation(DataSource.class).value();
            }
            //2.其次类注解
            if (target.isAnnotationPresent(DataSource.class)) {
                return target.getAnnotation(DataSource.class).value();
            }
        } catch (Exception e) {
            e.printStackTrace();
            LOG.error(MessageFormat.format("通过注解切换数据源时发生异常[class={0},method={1}]："
                    , target.getName(), method.getName()),e);
        }
        return null;
    }
}
